class DokuWikiLexer extends Lexer; 

options 
{
	k = 10 ;
	filter = true ;
	caseSensitive = false ;
}

BOLDSYMBOL :
	"**" ;
	
ITALICSYMBOL :
	"//" ;
	
UNDERLINESYMBOL :
	"__" ;

DELETED :
	"<del>" ;

DELETEDC :
	"</del>" ;
	
SUBSCRIPT :
	"<sub>" ;

SUBSCRIPTC :
	"</sub>" ;

SUPERSCRIPT :
	"<sup>" ;

SUPERSCRIPTC :
	"</sup>" ;
	
NEWLINESYMBOL :
	"\\\\" WHITESPACE ;
	
HEADERTABLESYMBOL :
	'^' ;
		
IMAGESYMBOL :
	"{{" ;
	
IMAGESYMBOLC :
	"}}" ;
		
ADDRESS :
	("www." | "http://") WORD ('.' WORD)+ ('/' (LETTER | DIGIT | PUNCTUATIONMARK)+)? ;
	
LINKSYMBOL :
	"[[" ;

LINKSYMBOLC : 
	"]]" ;

CODESECTION :
	NEWLINE ("  ") (' ')* ;

LISTSYMBOL :
	CODESECTION ('*' | '-') ;	

FOOTNOTESYMBOL :
	"((" ;

FOOTNOTESYMBOLC :
	"))" ;
	
QUOTINGSYMBOL :
	('>')+ " " ;	

HEADLINESYMBOL :
	"==" ('=')* ;
	
NUMBER :
	(DIGIT)+ ;
	
SIZE :
	'?' NUMBER ('x' NUMBER)? ;

WORD :
	(LETTER | DIGIT)+ ;

NOWIKI :
	"<nowiki>" ;
	
NOWIKIC :
	"</nowiki>" ;
	
CODE :
	"<code" (' ' (LETTER | DIGIT | '_' | '#' | '-')*)? ">" ;
	
CODEC :
	"</code>" ;

FILE :
	"<file" (' ' (LETTER | DIGIT | '_' | '#' | '-')*)? ">"  ;

FILEC :
	"</file>"  ;
	
HTML :
	"<html>" ;
	
HTMLC :
	"</html>" ;
	
PHP :
	"<php>" ;

PHPC :
	"</php>" ;

MAIL :
	'<' (WORD) ('.' WORD)* '@' WORD ('.' WORD)+ '>' ;
	
MARKUP :
	'<' ('/')? WORD (LETTER | DIGIT | PUNCTUATIONMARK | WHITESPACE)* '>' ;
	
REVERSE :
	"reverse" ;

AUTHOR :
	"author" ;
	
DATE :
	"date" ;

DESCRIPTION :
	"description" ;

INTERWIKI :
	'>' ;	
	
PUNCTUATIONMARK :
	']' | '\\' | '[' |'$' | '_' | '%' | '(' | ')' | ',' | '?' | ';' | '!' | '"' | '-' | '/' | ':' | '='  | '.' | '#' | '<' | '@' | '\'' | '*' | '{' ;

SPECIALPUNCTUATIONMARK :
	'}' | '>' ;
	
NOWIKI2 :
	"%%" ;

LINKTEXTSYMBOL :
	'|' ;
	
protected LETTER :
	'a'..'z' ;
	
protected DIGIT :
	'0'..'9' ;

WHITESPACE :
    ' '
    | '\t'
    | '\f' ;
  
NEWLINE :
	( "\r\n" { newline(); }
	| '\n' { newline(); }
	) ;  
  
class DokuWikiParser extends Parser;

options {
  buildAST=true;
}

dokuWikiFile! :
	node1:dokuWikiMarkupSection node2:dokuWikiFile 
		{ #dokuWikiFile = new DataModel((IComponent)#node1, (IComponent)#node2) ; }
	| node3:textBlock node4:dokuWikiFile 
		{ #dokuWikiFile = new DataModel(new Text(#node3.getText(), null), (IComponent)#node4) ; }
	| NEWLINE node5:dokuWikiFile 
		{ #dokuWikiFile = new DataModel(new Text("\n", null), (IComponent)#node5) ; }
	| () 
		{ #dokuWikiFile = null ; } ;

dokuWikiMarkupSection :
	(php | markupSection | list | footnoteText | noCache | noToc | html | codeBlock | table | qouting | boldText | italicText | underlineText | newLine | link | mail | headline | image | noWiki)  ;
	
boldText! :
	BOLDSYMBOL node:text BOLDSYMBOL 
		{ #boldText = new Text(#node.getText(), TextFormatting.BOLD) ; };

italicText! :
	ITALICSYMBOL node:text ITALICSYMBOL 
		{ #italicText = new Text(#node.getText(), TextFormatting.ITALIC) ; };

deletedText! :
	DELETED node:text DELETEDC
	{
		#deletedText = new Text(#node.getText(), TextFormatting.DELETED) ;	
	};
	
underlineText! :
	UNDERLINESYMBOL node:text UNDERLINESYMBOL
		{ #underlineText = new Text(#node.getText(), TextFormatting.UNDERLINE) ; };

footnoteText! :
	FOOTNOTESYMBOL t:text FOOTNOTESYMBOLC
		{ #footnoteText = new Text(#t.getText(), TextFormatting.FOOTNOTE) ; };

text! :
	t1:textBlock t2:text 
		{ #text = new Text(#t1.getText() + #t2.getText(), null) ;}  
	| NEWLINE t:text
		{ #text = new Text("\n" + #t.getText(), null) ;}  
	|	()
		{ #text = new Text("", null) ; } ;

newLine :
	NEWLINESYMBOL ;
	
link! :
	(LINKSYMBOL (a:ADDRESS | p:linkText) (LINKTEXTSYMBOL t:text)? LINKSYMBOLC)
		{
			if(#a != null)
				if( #t != null) 
					#link = new Link(new Text(#a.getText(), null), new Text(#t.getText(), null)) ; 
				else
					#link = new Link(new Text(#a.getText(), null), null) ;
			if(#p != null)
				if( #t != null) 
					#link = new Link(new Text(#p.getText(), null), new Text(#t.getText(), null)) ; 
				else
					#link = new Link(new Text(#p.getText(), null), null) ;
		}
	| a1:ADDRESS 
		{ #link = new Link(new Text(#a1.getText(), null), null) ; };

interWiki :
	INTERWIKI WORD ;

mail! : 
	m:MAIL
		{ #mail = new Mail(#m.getText().substring(1, #m.getText().length() - 1)) ; }  ;
	
linkText! : 
	t1:textBlock t2:linkText
	{
		String t2Text = "" ;
		if(#t2 != null)
			t2Text = #t2.getText() ;
		#linkText = new Text(#t1.getText() + t2Text, null) ;
	} 
	| () 
	{
		#linkText = null ;
	};

headline! :
	h1:HEADLINESYMBOL t:text h2:HEADLINESYMBOL 
	{
		if(#h1.getText().length() == #h2.getText().length())
			#headline = new Headline(#t.getText(), #h1.getText().length()) ;
		else 
		{
			if(#h1.getText().length() > #h2.getText().length())
				#headline = new Headline(#h1.getText().substring( #h2.getText().length()) + #t.getText(), #h2.getText().length()) ;
			else
				#headline = new Headline(#t.getText() + #h2.getText().substring( #h1.getText().length()), #h1.getText().length()) ;
				
		}
	};

textBlock :
	(WHITESPACE | WORD | PUNCTUATIONMARK | NUMBER | SPECIALPUNCTUATIONMARK); 

image! : 
	IMAGESYMBOL (p:linkText | a:ADDRESS) (s:SIZE)? (LINKTEXTSYMBOL t:text)? IMAGESYMBOLC
	{
		IComponent left = null ;
		if(#s != null)
		{
			String[] sizeTable = #s.getText().substring(1).split("x") ;
			String x = sizeTable[0] ;
			String y = null ;
			if(sizeTable.length > 1) 
				y = sizeTable[1] ;
			if(#p!= null)
				left = new ResizableImage(new Text(#p.getText(),null), new Size(x, y)) ;
			else
				left = new ResizableImage(new Text(#a.getText(), null), new Size(x, y)) ;
		}
		else
		{		
			if(#p != null)
				left = new Text(#p.getText(), null) ;
			else
				left = new Text(#a.getText(), null) ;
		}
		if(#t != null)
			#image = new Image(left, new Text(#t.getText(), null)) ;		
		else
			#image = new Image(left, null) ;		
	} ;

list! : 
	l:LISTSYMBOL
	{
		if(#l.getText().endsWith("*"))
			#list = new OrderedList("") ;
		else
			#list = new UnorderedList("") ;
		int level = #l.getText().length() / 2 - 1 ;
		((AbstractWikiList)#list).setLevel(level) ;
	} ;

qouting! :
	(q:QUOTINGSYMBOL)
	{
		#qouting = new Quote(#q.getText().length() - 1) ;
	} ;

table! :
	HEADERTABLESYMBOL head:tableHeader row:tableRows
	{
		#table = new Table((IComponent)#head, (IComponent)#row) ;
	};

tableHeader! :
	t:linkText HEADERTABLESYMBOL h:tableHeader 
	{
		#tableHeader = new TableHeader(new Text(#t.getText(), null), (IComponent)#h) ;
	}
	| NEWLINE
	{
		#tableHeader = null ;
	}
	 ;

tableRows! :
	LINKTEXTSYMBOL row:tableRow next:tableRows
	{
		#tableRows = new Table((IComponent)#row, (IComponent)#next) ;	
	}
	| () 
	{
		#tableRows = null ;
	} ; 
	
tableRow! :
	l:linkText LINKTEXTSYMBOL t:tableRow
	{	
		if(#l != null)
			#tableRow = new TableRow(new Text(#l.getText(), null), (IComponent)#t) ;
		else
			#tableRow = new TableRow(null, (IComponent)#t) ;
			
	}
	| NEWLINE
	{
		#tableRow = null ; ;
	};
		
noWiki! :
	NOWIKI t:dokuWikiFile NOWIKIC 
	{
		#noWiki = new NoWikiBlock(((IComponent)#t).toDokuWiki()) ; ;	
	}
	| NOWIKI2 ; //prawie jak wyzej....
	
codeBlock! :
	c:CODE t:dokuWikiFile CODEC
	{
		#codeBlock = new CodeBlock(((IComponent)#t).toDokuWiki()) ;
		if(#c.getText().length() > 6)
		{
			String language = #c.getText().substring(#c.getText().indexOf(' ') + 1, #c.getText().length() -1) ;
			((CodeBlock)#codeBlock).setLanguage(language) ;
		}
	}
	| f:FILE s:dokuWikiFile FILEC
	{
		#codeBlock = new CodeBlock(((IComponent)#s).toDokuWiki()) ;
		if(#f.getText().length() > 6)
		{
			String language = #f.getText().substring(#f.getText().indexOf(' ') + 1, #f.getText().length() -1) ;
			((CodeBlock)#codeBlock).setLanguage(language) ;
		}
	}
	| CODESECTION u:linkText NEWLINE
	{
		#codeBlock = new CodeBlock(#u.getText()) ;
	} ;
	
html! :
	HTML d:dokuWikiFile HTMLC
	{
		#html  = new HTMLSection(((IComponent)#d).toDokuWiki()) ;
	} ;
	
php! :
	PHP d:dokuWikiFile PHPC
	{
		#php = new PHPSection(((IComponent)#d).toDokuWiki()) ;	
	};	
	
markupSection! :
	m:MARKUP
	{
		#markupSection = new Text(#m.getText(), null) ;
	} ;
	
noCache :
	NOCACHE ;

noToc :
	NOTOC ;